package ru.amse.tsyganov.jumleditor.view.activity;

import java.util.ArrayList;
import java.util.List;

import ru.amse.tsyganov.jumleditor.model.activity.Decision;
import ru.amse.tsyganov.jumleditor.model.activity.Transition;
import ru.amse.tsyganov.jumleditor.model.common.Edge;
import ru.amse.tsyganov.jumleditor.model.common.GraphModel;
import ru.amse.tsyganov.jumleditor.properties.BooleanProperty;
import ru.amse.tsyganov.jumleditor.properties.StringProperty;
import ru.amse.tsyganov.jumleditor.validator.Problem;
import ru.amse.tsyganov.jumleditor.validator.Validator;
import ru.amse.tsyganov.jumleditor.view.ConnectionPoint;
import ru.amse.tsyganov.jumleditor.view.SelectedItems;
import ru.amse.tsyganov.jumleditor.view.Validity;
import ru.amse.tsyganov.jumleditor.view.ViewVisitor;
import ru.amse.tsyganov.jumleditor.view.activepoints.ActivePoint;
import ru.amse.tsyganov.jumleditor.view.activepoints.TransitionActivePoint;
import ru.amse.tsyganov.jumleditor.view.common.EdgeView;
import ru.amse.tsyganov.jumleditor.view.common.GraphView;
import ru.amse.tsyganov.jumleditor.view.preferences.Images;

public class TransitionView<T extends Transition> extends EdgeView<T> {
	
	private StringProperty guardExpressionProperty;
	
	private BooleanProperty guardProperty;
	
	public TransitionView(T model,
			GraphView<? extends GraphModel> activityGraphView,
			ConnectionPoint sourceConnectionPoint,
			ConnectionPoint targetConnectionPoint) {
		
		super(model, activityGraphView, sourceConnectionPoint, 
				targetConnectionPoint);
		
		initProperties();
	}
	
	@Override
	public String getText() {
		if (getModel().isGuard()) {
			return "[" + getModel().getGuardExpression() + "]";
		}
		return "";
	}

	@Override
	public void accept(ViewVisitor v) {
		v.visitTransitionView(this);
	}
	
	private void initProperties() {
		
		guardProperty = new BooleanProperty("Guard") {

			@Override
			public Boolean getPropertyValue() {
				return getModel().isGuard();
			}

			@Override
			public void setPropertyValue(Boolean newValue) {
				getModel().setGuard(newValue);
				getActivityGraphView().getModel().fireModelChanged();
			}
						
		};
		
		super.getProperties().addProperty(guardProperty);
		
		guardExpressionProperty = new StringProperty("Guard expression") {

			@Override
			public String getPropertyValue() {
				return getModel().getGuardExpression();
			}

			@Override
			public void setPropertyValue(String newValue) {
				getModel().setGuardExpression(newValue);
				getActivityGraphView().getModel().fireModelChanged();
			}
			
			@Override
			public boolean canModify() {
				return getModel().isGuard();
			}
			
		};
		
		super.getProperties().addProperty(guardExpressionProperty);
	}
	
	@Override
	public StringProperty getMainProperty() {
		return guardExpressionProperty;
	}

	public String getClassName() {
		return "TransitionView";
	}

	@Override
	public List<Problem> getInnerProblems() {
		List<Problem> problems = new ArrayList<Problem>();
		if (getModel().isGuard()) {
			if (!(getModel().getSource().getContainer() 
					instanceof Decision)) {
				
				SelectedItems problemSpace = new SelectedItems();
				problemSpace.selectedTransitionsAdd(this);
				
				String message = Validator.ERROR +  
					": guard is not allowed here";
				
				problems.add(new Problem(message, 
						problemSpace, Images.getErrorImage()));
				
				setValidity(Validity.ERROR);
			} else if (getModel().getGuardExpression().length() == 0) {
				SelectedItems problemSpace = new SelectedItems();
				problemSpace.selectedTransitionsAdd(this);
				
				String message = Validator.WARNING +  
					": guard expression is empty";
				
				problems.add(new Problem(message, 
						problemSpace, Images.getWarningImage()));
				
				setValidity(Validity.WARNING);
			}
		} else {
			if (getModel().getSource().getContainer() 
					instanceof Decision &&
					getModel().getSource().getContainer().
					getStateVertex().outgoingTransitionsSize() > 1) {
				
				SelectedItems problemSpace = new SelectedItems();
				problemSpace.selectedTransitionsAdd(this);
				
				String message = Validator.ERROR +  
					": guard should be here";
				
				problems.add(new Problem(message, 
						problemSpace, Images.getErrorImage()));
				
				setValidity(Validity.ERROR);
			}
		}
		return problems;
	}

	@Override
	public List<ActivePoint> createActivePoints() {
		List<ActivePoint> points = new ArrayList<ActivePoint>(2);
		TransitionActivePoint startPoint = new TransitionActivePoint(true) {
			@Override
			public int getCurrentActivePointX() {
				return getStartPoint().x;
			}
			@Override
			public int getCurrentActivePointY() {
				return getStartPoint().y;
			}
			@Override
			public EdgeView<? extends Edge> getEdgeView() {
				return TransitionView.this;
			}
			@Override
			public GraphView<? extends GraphModel> getContainer() {
				return getActivityGraphView();
			}
		};
		
		TransitionActivePoint endPoint = new TransitionActivePoint(false) {
			@Override
			public int getCurrentActivePointX() {
				return getEndPoint().x;
			}
			@Override
			public int getCurrentActivePointY() {
				return getEndPoint().y;
			}
			@Override
			public EdgeView<? extends Edge> getEdgeView() {
				return TransitionView.this;
			}
			@Override
			public GraphView<? extends GraphModel> getContainer() {
				return getActivityGraphView();
			}
		};
		points.add(startPoint);
		points.add(endPoint);
		return points;
	}
}
